package org.fireflow2.designer.eclipse.policies;

import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gef.requests.GroupRequest;
import org.eclipse.swt.widgets.Shell;
import org.fireflow.pdl.fpdl20.diagram.Fpdl20DiagramElement;
import org.fireflow2.designer.eclipse.commands.AcceptChildCommand;
import org.fireflow2.designer.eclipse.commands.CommonMoveCommand;
import org.fireflow2.designer.eclipse.commands.CommonResizeCommand;
import org.fireflow2.designer.eclipse.commands.OrphanChildCommand;
import org.fireflow2.designer.eclipse.commands.group.CreateGroupCommand;
import org.fireflow2.designer.eclipse.commands.pool.CreatePoolCommand;
import org.fireflow2.designer.eclipse.commands.pool.PoolResizeCommand;
import org.fireflow2.designer.eclipse.commands.service.AbstractServiceCreationCommand;
import org.fireflow2.designer.eclipse.commands.service.human.HumanServiceCreationCommand;
import org.fireflow2.designer.eclipse.commands.service.java.JavaServiceCreationCommand;
import org.fireflow2.designer.eclipse.commands.workflownode.CreateActivityCommand;
import org.fireflow2.designer.eclipse.commands.workflownode.CreateWorkflowNodeCommand;
import org.fireflow2.designer.eclipse.modelwrapper.ModelWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.NodeWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.Wrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.GroupWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.PoolWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.StartNodeWrapper;
import org.fireflow2.designer.eclipse.palette.DiagramElementSubType;
import org.fireflow2.designer.eclipse.parts.basic.BasicLanePart;
import org.fireflow2.designer.eclipse.parts.basic.BasicStartNodePart;

public class CommonXYLayoutEditPolicy extends XYLayoutEditPolicy {

    protected Command createAddCommand(EditPart child, Object constraint) {
    	if (child instanceof BasicLanePart){
    		return null;
    	}
    	if (child instanceof BasicStartNodePart){
    		StartNodeWrapper wrapper = (StartNodeWrapper)child.getModel();
    		String attachedToId = wrapper.getAttachedToWrapperId();
    		if (attachedToId!=null && !attachedToId.trim().equals("")){
    			return null;
    		}
    	}
    	Wrapper parentWrapper = (Wrapper)this.getHost().getModel();
    	NodeWrapper childModel = (NodeWrapper)child.getModel();
    	
    	if ((parentWrapper instanceof GroupWrapper ) && 
    			(childModel instanceof GroupWrapper)){
    		return null;
    	}
    	
    	AcceptChildCommand acceptCmd = new AcceptChildCommand();
    	acceptCmd.setNodeWrapper(childModel);
        Rectangle rect = ((Rectangle) constraint);
        Point location = rect.getLocation();
        acceptCmd.setNewLocation(location);
        acceptCmd.setParentWrapper(parentWrapper);
        return acceptCmd;
    }

	protected Command createChangeConstraintCommand(
			ChangeBoundsRequest request, EditPart child, Object constraint) {
		if (REQ_MOVE_CHILDREN.equals(request.getType())){
	        Object model = child.getModel();
	        if (!(model instanceof NodeWrapper)){
	        	return null;
	        }
			CommonMoveCommand cmd = new CommonMoveCommand();
			cmd.setModelWrapper((NodeWrapper)model);
			cmd.setMoveDelta(request.getMoveDelta());

			return cmd;
		}
		else if (REQ_RESIZE_CHILDREN.equals(request.getType())){
	        Object model = child.getModel();
	        if (!(model instanceof NodeWrapper)){
	        	return null;
	        }
	        Rectangle rect = ((Rectangle) constraint);
	        Point location = rect.getLocation();
	        if (model instanceof PoolWrapper){
				PoolResizeCommand cmd = new PoolResizeCommand();
				cmd.setModelWrapper((NodeWrapper)model);
				cmd.setSizeDelta(request.getSizeDelta());
				cmd.setNewLocation(location);
				return cmd;
	        }else{
				CommonResizeCommand cmd = new CommonResizeCommand();
				cmd.setModelWrapper((NodeWrapper)model);
				cmd.setSizeDelta(request.getSizeDelta());
				cmd.setNewLocation(location);
				return cmd;
	        }       
		}
		else{
			return createChangeConstraintCommand(child, constraint);
		}
		
	}
    
    protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
    	System.out.println("Inside CommonXYLayoutEditPart:: Hi i am here");
    	
    	return null;
    }

    protected Command getCreateCommand(CreateRequest request) {
    	Fpdl20DiagramElement newObj = (Fpdl20DiagramElement) request.getNewObject();
    	DiagramElementSubType subType = (DiagramElementSubType)request.getNewObjectType();
    	if (newObj.equals(Fpdl20DiagramElement.START_NODE) 
        		|| newObj.equals(Fpdl20DiagramElement.ROUTER)
        		|| newObj.equals(Fpdl20DiagramElement.END_NODE)) {
        	if(DiagramElementSubType.START_CATCH_FAULT_START.equals(subType) ||
        			DiagramElementSubType.START_CATCH_COMPENSATION_START.equals(subType)){
        		return null;//这两种类型的StartNode只能够放在Activity的边上。
        	}
            Rectangle constraint = (Rectangle) getConstraintFor(request);

        	CreateWorkflowNodeCommand cmd = new CreateWorkflowNodeCommand();
        	ModelWrapper parentWrapper = (ModelWrapper)getHost().getModel();
        	cmd.setParentWrapper(parentWrapper);
            cmd.setNewDiagramElement(newObj);
            cmd.setDiagramElementSubType(subType);
            cmd.setRect(constraint);
            return cmd;
        }
    	else if (newObj.equals(Fpdl20DiagramElement.ACTIVITY)){
    		CompoundCommand compounCommand = new CompoundCommand();
    		ModelWrapper parentWrapper = (ModelWrapper)getHost().getModel();
    		
    		AbstractServiceCreationCommand serviceCreationCommand = null;
    		if (DiagramElementSubType.SERVICE_JAVA.equals(subType)){
    			serviceCreationCommand = new JavaServiceCreationCommand();
    			Shell shell = this.getHost().getViewer().getControl().getShell();
    			serviceCreationCommand.setShell(shell);
    		}
    		else if (DiagramElementSubType.SERVICE_HUMAN.equals(subType)){
    			serviceCreationCommand = new HumanServiceCreationCommand();
    		}
    		if (serviceCreationCommand!=null){
    			serviceCreationCommand.setParentWrapper(parentWrapper);
    			compounCommand.add(serviceCreationCommand);
    		}
    		
            Rectangle constraint = (Rectangle) getConstraintFor(request);
    		CreateActivityCommand createActivityCommand = new CreateActivityCommand();
    		createActivityCommand.setServiceCreationCommand(serviceCreationCommand);
    		createActivityCommand.setParentWrapper(parentWrapper);
    		createActivityCommand.setNewDiagramElement(newObj);
    		createActivityCommand.setDiagramElementSubType(subType);
    		createActivityCommand.setRect(constraint);
            
    		compounCommand.add(createActivityCommand);
    		

    		return compounCommand;
    	}
        
        else if (newObj.equals(Fpdl20DiagramElement.POOL)){
            Rectangle constraint = (Rectangle) getConstraintFor(request);

        	CreatePoolCommand cmd = new CreatePoolCommand();
        	ModelWrapper modelWrapper = (ModelWrapper)getHost().getModel();
        	cmd.setParentWrapper(modelWrapper);

            cmd.setNewDiagramElement(newObj);
            cmd.setDiagramElementSubType(subType);
            cmd.setRect(constraint);
            return cmd;
        }
        else if (newObj.equals(Fpdl20DiagramElement.GROUP)){
            Rectangle constraint = (Rectangle) getConstraintFor(request);

        	CreateGroupCommand cmd = new CreateGroupCommand();
        	ModelWrapper modelWrapper = (ModelWrapper)getHost().getModel();
        	cmd.setParentWrapper(modelWrapper);

            cmd.setNewDiagramElement(newObj);
            cmd.setDiagramElementSubType(subType);
            cmd.setRect(constraint);
            return cmd;
        }

        return null;
    }
    
//	protected Command getOrphanChildrenCommand(GroupRequest request) {
//		return null;
//	}
	protected Command getOrphanChildrenCommand(Request request) {
//		System.out.println("Inside CommonXYLoyoutEditPart:: "+request.toString());
		if (!(request instanceof GroupRequest)){
			return null;
		}
		GroupRequest groupRequest = (GroupRequest)request;
		List<EditPart> editPartList = groupRequest.getEditParts();
		if (editPartList==null || editPartList.size()==0)return null; 
		CompoundCommand command = new CompoundCommand();
		for (EditPart editPart : editPartList){
			OrphanChildCommand ophanChildCmd = new OrphanChildCommand();
			ophanChildCmd.setNodeWrapper((NodeWrapper)editPart.getModel());
			command.add(ophanChildCmd);
		}
		return command;
	}


    protected Command getDeleteDependantCommand(Request request) {
        return null;
    }
	protected EditPolicy createChildEditPolicy(EditPart child) {
		return new CommonResizableEditPolicy();
	}
}


